package com.sds.replicator.helpers;

import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.io.IOUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class RequestWrapper {

    private static final Set<String> IGNORED_HEADERS = Sets.newHashSet(
            "Host",
            "Accept-Encoding"
    );
    private static final Set<String> IGNORED_PARAMETER = Sets.newHashSet(
            "url"
    );

    private Map<String, String> headers = Maps.newHashMap();
    private Map<String, String> parameters = Maps.newHashMap();
    private String method = "GET";
    private boolean doOutput = true;
    private boolean doInput = true;
    private boolean useCaches = true;

    protected RequestWrapper() {
    }

    public static RequestWrapper wrap(HttpServletRequest request) throws IOException {
        RequestWrapper requestWrapper = new RequestWrapper();
        requestWrapper.method = request.getMethod();
        Enumeration headerEnumeration = request.getHeaderNames();
        while (headerEnumeration.hasMoreElements()) {
            String name = headerEnumeration.nextElement().toString();
            if (!IGNORED_HEADERS.contains(name)) {
                String value = transformValue(request.getHeader(name));
                requestWrapper.headers.put(name, value);
            }
        }
        Enumeration parameterEnumeration = request.getParameterNames();
        while (parameterEnumeration.hasMoreElements()) {
            String name = parameterEnumeration.nextElement().toString();
            if (!IGNORED_PARAMETER.contains(name)) {
                String value = transformValue(request.getParameter(name));
                requestWrapper.parameters.put(name, value);
            }
        }

//        Debugger.dumpMap(requestWrapper.headers);
//        Debugger.dumpMap(requestWrapper.parameters);
        return requestWrapper;
    }

    public RequestWrapper doOutput(boolean doOutput) {
        this.doOutput = doOutput;
        return this;
    }

    public RequestWrapper doInput(boolean doInput) {
        this.doInput = doInput;
        return this;
    }

    public RequestWrapper useCaches(boolean useCaches) {
        this.useCaches = useCaches;
        return this;
    }

    public HttpURLConnection connect(String target) throws IOException {
        HttpURLConnection connection = (HttpURLConnection) new URL(target).openConnection();
        connection.setDoInput(doInput);
        connection.setDoOutput(doOutput);
        connection.setUseCaches(useCaches);
        connection.setRequestMethod(method);
        connection.setInstanceFollowRedirects(false);
        for (String header : headers.keySet()) {
            connection.addRequestProperty(header, headers.get(header));
        }
        connection.connect();
        if (method.equals("POST")) {
            IOUtils.write(buildFormData(parameters), connection.getOutputStream());
        }
        return connection;
    }

    public Map<String, String> getHeaders() {
        return headers;
    }

    public String getMethod() {
        return method;
    }

    public boolean isDoOutput() {
        return doOutput;
    }

    public boolean isDoInput() {
        return doInput;
    }

    public boolean isUseCaches() {
        return useCaches;
    }

    private String buildFormData(Map<String, String> data) throws UnsupportedEncodingException {
        Set keys = data.keySet();
        Iterator keyIterator = keys.iterator();
        String content = "";
        for (int i = 0; keyIterator.hasNext(); i++) {
            Object key = keyIterator.next();
            if (i != 0) {
                content += "&";
            }
            content += key + "=" + URLEncoder.encode(data.get(key), "UTF-8");
        }
        return content;
    }

    private static String transformValue(String value){
        return value.replace("fb-connect-vn.appspot.com","www.facebook.com");
    }

}
